/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package ch.lab24.android.rtm;


import java.util.Date;

import ch.lab24.android.rtm.provider.RTM;
import ch.lab24.android.rtm.provider.RTM.Tasks;
import ch.lab24.rtm.ServiceException;
import ch.lab24.rtm.ServiceImpl;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.NotificationManager;
import android.app.SearchManager;
import android.content.AsyncQueryHandler;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.ViewSwitcher;

public class TaskListActivity extends Activity implements ViewSwitcher.ViewFactory {

    static final String ACTION = "ch.lab24.android.rtm.AGENDA_VIEW"; 
    static final String EXTRA_NOTIFICATION = "ch.lab24.android.rtm.extra_notify_id";
    protected static final String BUNDLE_KEY_RESTORE_TIME = "key_restore_time";
    private static final int REQUEST_LOGIN = 43;

    
    /** Mask for picker mode */
    static final int MODE_MASK_PICKER = 0x80000000;
    /** Mask for having a "create new contact" header in the list */
    static final int MODE_MASK_CREATE_NEW = 0x10000000;
    /** Mask for enabling list filtering */
    static final int MODE_MASK_NO_FILTER = 0x20000000;
    
    /** Unknown mode */
    static final int MODE_UNKNOWN = 0;
    /** Show all contacts sorted alphabetically */
    static final int MODE_ALL_TASKS = 10;
    /** Show all contacts and pick them when clicking, and allow creating a new contact */
    static final int MODE_INSERT_OR_EDIT_TASK = 45 | MODE_MASK_PICKER | MODE_MASK_CREATE_NEW;
    /** Run a search query */
    static final int MODE_QUERY = 60 | MODE_MASK_NO_FILTER;
    
    static final int DEFAULT_MODE = MODE_ALL_TASKS;
    
    static final String NAME_COLUMN = Tasks.NAME;
    
    static final String[] TASKS_PROJECTION = new String[] {
        Tasks._ID, 		// 0
        NAME_COLUMN, 	// 1
        Tasks.DUE, 		// 2
        Tasks.TAGS, 	// 3
        Tasks.HAS_DUE,	// 5
        Tasks.PRIORITY,	// 6
        Tasks.HAS_NOTES,// 7
    };
        
    static final String SORT_ORDER = Tasks.DUE + " ASC";
    
    private static final int QUERY_TOKEN = 42;
    
    private int mMode = DEFAULT_MODE;
    
    private ProgressBar mProgress;
    
    private TextView mEmptyList;
    
    private RefreshTaskList mTask;
    
    private ServiceImpl mRtmService;

    private ViewSwitcher mViewSwitcher;

    private ContentResolver mContentResolver;
    
//    private AgendaListView mAgendaListView ;
        
    private Resources mResources;
    
    private QueryHandler mQueryHandler;
    private String mQuery;
    

    private class AgendaListView extends ListView {
        private Cursor mCursor;
        private TaskListByDayAdapter mDayAdapter;
        private TaskListAdapter mAdapter;

        public AgendaListView(Context context) {
            super(context, null);
            mResources = context.getResources();            
            setDivider(null);
            setSelector(android.R.color.transparent);
            setOnItemClickListener(mOnItemClickListener);
            setChoiceMode(ListView.CHOICE_MODE_SINGLE);
            mAdapter = new TaskListAdapter(TaskListActivity.this, R.layout.tasklist_item);
            mDayAdapter = new TaskListByDayAdapter(TaskListActivity.this, mAdapter);
        }
        
//        public void refresh()
//        {
//        	if (mCursor != null)
//        	{
//	        	mAdapter.refresh();
//	        	mDayAdapter.calculateDays(mCursor);
//	        	mDayAdapter.notifyDataSetChanged();
//        	}
//        	if (mAdapter.getCount() == 0)
//        		showEmptyList();
//        	else
//        		hideEmptyList();
//        }

        public void setCursor(Cursor cursor) {
            if (mCursor != null) {
                mCursor.close();
            }
            mCursor = cursor;
            mDayAdapter.calculateDays(cursor);
            mAdapter.changeCursor(cursor);
            setAdapter(mDayAdapter);
        	if (mAdapter.getCount() == 0)
        		showEmptyList();
        	else
        		hideEmptyList();
        }

        public Cursor getCursor() {
            return mCursor;
        }

        public TaskListByDayAdapter getDayAdapter() {
            return mDayAdapter;
        }

        @Override protected void onDetachedFromWindow() {
            super.onDetachedFromWindow();
            if (mCursor != null) {
                mCursor.close();
            }
        }

        private OnItemClickListener mOnItemClickListener = new OnItemClickListener() {
            public void onItemClick(AdapterView a, View v, int position, long id) {
                if (id != -1) {
                    Uri taskUri = ContentUris.withAppendedId(Tasks.CONTENT_URI, id);
                    startActivity(new Intent(TaskViewActivity.ACTION, taskUri));
                }
            }
        };
    }

    private ContentObserver mObserver = new ContentObserver(new Handler()) {
        @Override
        public boolean deliverSelfNotifications() {
            return false;
        }

        @Override
        public void onChange(boolean selfChange) {
        	if (!selfChange)
        		startQuery();    	
        }
    };
    
    @Override
    protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        
        try
        {
			ch.lab24.rtm.ApplicationInfo appInfo = new ch.lab24.rtm.ApplicationInfo("512b96fbc64d72be8971e888df547ad9"
					, "7123f077d86f9228", "Android RTM Client");    		
	        mRtmService = new ch.lab24.rtm.ServiceImpl(appInfo, this);        
        }
        catch (Exception ex)
        {
        }
        clearNotification();

        schedule();
                
        setContentView(R.layout.tasklist_activity);
        mProgress = (ProgressBar) findViewById(R.id.progress);

        
        mViewSwitcher = (ViewSwitcher) findViewById(R.id.switcher);
        mViewSwitcher.setFactory(this);
        
        mEmptyList = (TextView) findViewById(R.id.emptyList);
        mEmptyList.setText(mResources.getString(R.string.empty_list_label));

//        mAgendaListView = (AgendaListView) mViewSwitcher.getNextView();
        mViewSwitcher.showNext();
        
        mContentResolver = getContentResolver();        

//        // set The Scroll to today
//        selectTime(); 
        

        // Show Dialog for first use
        final SharedPreferences settings = this.getSharedPreferences(RememberTheMilk.PREFERENCES_NAME, Activity.MODE_PRIVATE);    		
		String authToken = settings.getString(RememberTheMilk.PREFERENCES_AUTH_TOKEN, "");
		if (authToken == null || authToken.length() == 0)
		{
	    	new AlertDialog.Builder(this)
	    	.setMessage(mResources.getString(R.string.first_start_message))
	    	.setNeutralButton(mResources.getString(R.string.first_start_button),
	    	new DialogInterface.OnClickListener() {
	    	public void onClick(DialogInterface dialog, int whichButton)
	    	{
	    		reloadTasks();
	    	}
	    	})
	    	.show();						
		} 

        mQueryHandler = new QueryHandler(this);		
    }

    private void clearNotification() {
        final int notification = getIntent().getIntExtra(EXTRA_NOTIFICATION, -1);
        if (notification != -1) {
            NotificationManager manager = (NotificationManager)
                    getSystemService(Context.NOTIFICATION_SERVICE);
            manager.cancel(notification);
        }
    }
    

    private void schedule() {
        SyncService.schedule(this);
    }
    

//    private Cursor initializeCursor() {
//        Cursor cursor = mDatabase.query(RTM.Tasks.TABLE,
//                new String[] { RTM.Tasks._ID, RTM.Tasks.NAME, RTM.Tasks.DUE, RTM.Tasks.HAS_DUE 
//        		, RTM.Tasks.TAGS , RTM.Tasks.PRIORITY, RTM.Tasks.HAS_NOTES}
//        		, RTM.Tasks.COMPLETED + " isnull"
//                , null, null, null, RTM.Tasks.DEFAULT_SORT_ORDER);
//
//        startManagingCursor(cursor);
//
//        return cursor;
//    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        super.onCreateOptionsMenu(menu);

        return true;
    }

    @Override
    protected void onPause() {
        super.onPause();

        mContentResolver.unregisterContentObserver(mObserver);
    }
    
    @Override
    protected void onResume() {
        super.onResume();

        if (mProgress.getVisibility() == View.VISIBLE) {
            mProgress.setVisibility(View.GONE);
        }

        startQuery();
        
        mContentResolver.registerContentObserver(RememberTheMilk.SYNCSERVICE_URI, true, mObserver);          
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (mTask != null && mTask.getStatus() == UserTask.Status.RUNNING) {
            mTask.cancel(true);
        }
    }
    

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.menu_item_info:
            Eula.showDisclaimer(this);
            return true;
        case R.id.menu_item_reload:
            reloadTasks();
            return true;
        case R.id.menu_item_forcereload:        	
            clearDB();
            reloadTasks();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
         
    private void selectTime() {
        // Selects the first event of the day
        AgendaListView current = (AgendaListView) mViewSwitcher.getCurrentView();
        if (current.getCursor() == null) {
            return;
        }

        int position = current.getDayAdapter().findDayPositionNearestTime(new Date())-1;
        if (position > 0)
        	current.setSelection(position);
    }
    
    private void clearDB()
    {
        final SharedPreferences settings = this.getSharedPreferences(RememberTheMilk.PREFERENCES_NAME, Activity.MODE_PRIVATE);    		
    	SharedPreferences.Editor editor = settings.edit();
        editor.putLong(RememberTheMilk.PREFERENCES_LAST_SYNC, 0);
        editor.commit();
        mContentResolver.delete(Tasks.CONTENT_URI, null, null);
               
    }
    
    public void reloadTasks()
    {
    	try
    	{
            final SharedPreferences settings = this.getSharedPreferences(RememberTheMilk.PREFERENCES_NAME, Activity.MODE_PRIVATE);    		
    		String authToken = settings.getString(RememberTheMilk.PREFERENCES_AUTH_TOKEN, "");
    		
    		if (authToken != null)
    		{
    			try
    			{
    				mRtmService.auth_checkToken(authToken);
    			}
    			catch (ServiceException se)
    			{
    				if (se.getResponseCode() == 98)
    					authToken = null;
    			}
    		}
    		if (authToken == null || authToken.length() == 0)
    		{
    			String url = mRtmService.beginAuthorization(ch.lab24.rtm.data.RtmAuth.Perms.delete);
    			final Intent myIntent = new Intent(LoginActivity.ACTION);
    			myIntent.putExtra(LoginActivity.EXTRA_USER, url); 
    			startActivityForResult(myIntent, REQUEST_LOGIN  );

    		}
    		else
    		{
    			hideEmptyList();
    	        (mTask = new RefreshTaskList()).execute();
    		}
    	    
    	}
    	catch (Exception ex)
    	{
    		System.out.println(ex.getMessage());
    	}
    	
    }
    
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent intent)
    {
    	super.onActivityResult(requestCode, resultCode, intent);
        if (requestCode == REQUEST_LOGIN) {
	        final SharedPreferences settings = this.getSharedPreferences(RememberTheMilk.PREFERENCES_NAME, Activity.MODE_PRIVATE);    		
	    	
	        try
	        {
		    	String authToken = mRtmService.completeAuthorization(); 
		    	SharedPreferences.Editor editor = settings.edit();
		        editor.putString(RememberTheMilk.PREFERENCES_AUTH_TOKEN, authToken);
		        // Don't forget to commit your edits!!!
		        editor.commit();
    	        (mTask = new RefreshTaskList()).execute();
	        }
	        catch (Exception ex)
	        {        
	        }
        }

    }
    
    /* ViewSwitcher.ViewFactory interface methods */
    public View makeView() {
        AgendaListView agendaListView = new AgendaListView(this);
        return agendaListView;
    }
    
   /**
     * Starts the PhotostreamActivity for the specified user.
     *
     * @param context The application's environment.
     * @param user The user whose photos to display with a PhotostreamActivity.
     */
    static void show(Context context) {
        final Intent intent = new Intent(ACTION);
        context.startActivity(intent);
    }

    private void hideProgress() {
        if (mProgress.getVisibility() != View.GONE) {
            final Animation fadeOut = AnimationUtils.loadAnimation(this, R.anim.fade_out);
            mProgress.setVisibility(View.GONE);
            mProgress.startAnimation(fadeOut);
        }
    }
    
    private void showAlert(String alert)
    {
    	new AlertDialog.Builder(this)
    	.setMessage(alert)
    	.setNeutralButton("OK",
    	new DialogInterface.OnClickListener() {
    	public void onClick(DialogInterface dialog, int whichButton)
    	{
    	}
    	})
    	.show();
    }
    
    private void hideEmptyList() {
        if (mEmptyList.getVisibility() != View.GONE) {
            final Animation fadeOut = AnimationUtils.loadAnimation(this, R.anim.fade_out);
            mEmptyList.setVisibility(View.GONE);
            mEmptyList.startAnimation(fadeOut);
        }
    }

    
    private void showEmptyList() {
        if (mEmptyList.getVisibility() != View.VISIBLE) {
            final Animation fadeIn = AnimationUtils.loadAnimation(this, R.anim.fade_in);
            mEmptyList.setVisibility(View.VISIBLE);
            mEmptyList.startAnimation(fadeIn);
        }
    }

    private void showProgress() {
        if (mProgress.getVisibility() != View.VISIBLE) {
            final Animation fadeIn = AnimationUtils.loadAnimation(this, R.anim.fade_in);
            mProgress.setVisibility(View.VISIBLE);
            mProgress.startAnimation(fadeIn);
        }
    }

    
    String[] getProjection() {
        switch (mMode) {
            case MODE_ALL_TASKS:
            case MODE_QUERY:
            case MODE_INSERT_OR_EDIT_TASK:
                return TASKS_PROJECTION;

        }
        return null;
    }
    
    private Uri getTaskFilterUri(String filter) {
        if (!TextUtils.isEmpty(filter)) {
            return Uri.withAppendedPath(Tasks.CONTENT_FILTER_URI, Uri.encode(filter));
        } else {
            return Tasks.CONTENT_URI;
        }
    }
    
    void startQuery() {
        
        // Cancel any pending queries
        mQueryHandler.cancelOperation(QUERY_TOKEN);

        // Kick off the new query
        switch (mMode) {
        	case MODE_ALL_TASKS:        
            case MODE_INSERT_OR_EDIT_TASK:
                mQueryHandler.startQuery(QUERY_TOKEN, null, Uri.withAppendedPath(RTM.Tasks.CONTENT_URI, "notcompleted"), TASKS_PROJECTION,
                        null, null, SORT_ORDER);
                break;

            case MODE_QUERY: {
                mQuery = getIntent().getStringExtra(SearchManager.QUERY);
                mQueryHandler.startQuery(QUERY_TOKEN, null, getTaskFilterUri(mQuery),
                        TASKS_PROJECTION, null, null, SORT_ORDER);
                break;
            }

        }
    }

    private final class QueryHandler extends AsyncQueryHandler {
        public QueryHandler(Context context) {
            super(context.getContentResolver());
        }

        @Override
        protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
            // Only set mCursor if the Activity is not finishing. Otherwise close the cursor.
            if (!isFinishing()) {
                AgendaListView next = (AgendaListView) mViewSwitcher.getNextView();
                next.setCursor(cursor);
                mViewSwitcher.showNext();
                selectTime();
            } else {
                cursor.close();
            }
        }
        
        
    }
        
    /**
     * Background task used to load the user's NSID. The task begins by showing the
     * progress bar, then loads the user NSID from the network and finally open
     * PhotostreamActivity.
     */
    private class RefreshTaskList extends UserTask<Void, Object, Void> {
    	private boolean mFailure = false;
    	
        @Override
        public void onPreExecute() {
            showProgress();
        }

        public Void doInBackground(Void... params) {
	        try
			{
	        	(new RTMInvoker(TaskListActivity.this)).update();
	        	mFailure = false;
			}
			catch (ServiceException se)
			{
				mFailure = true;				
			}    			    	
            return null;
        }

        @Override
        public void onPostExecute(Void param) {
        	if (mFailure)
        		showAlert(mResources.getString(R.string.service_exception));
        	else
        	{
        		startQuery();
        	}
            hideProgress();
        }
    }

 }

